/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package service;

import com.openbrew.openbrewrf.OBAlarm;
import com.openbrew.openbrewrf.OBReminder;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import javax.ejb.Stateless;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import model.AlarmType;
import static model.AlarmType.TEXT_MESSAGE;
import model.RepetitionType;
import tools.GoogleCalendar;
import tools.SystemEmailer;

/**
 *
 * @author dchapman
 */
@Stateless
@Path("com.openbrew.openbrewrf.obreminder")
public class OBReminderFacadeREST extends AbstractFacade<OBReminder> {
    @PersistenceContext(unitName = "com.openBrew_openBrewRF_war_1.0PU")
    private EntityManager em;
    private final List<Date> repeatDates = new ArrayList<Date>();
    
    private List<toRun> rmdrsToRun = new ArrayList<toRun>();
    
    private class toRun {
        private OBReminder rmdr;
        private OBAlarm alarm;
        private Date date;

        public toRun(OBReminder rmdr, OBAlarm alarm, Date date) {
            this.rmdr = rmdr;
            this.alarm = alarm;
            this.date = date;
        }

        public OBReminder getRmdr() {
            return rmdr;
        }

        public void setRmdr(OBReminder rmdr) {
            this.rmdr = rmdr;
        }

        public OBAlarm getAlarm() {
            return alarm;
        }

        public void setAlarm(OBAlarm alarm) {
            this.alarm = alarm;
        }

        public Date getDate() {
            return date;
        }

        public void setDate(Date date) {
            this.date = date;
        }
    }

    public OBReminderFacadeREST() {
        super(OBReminder.class);
    }
    
    @POST
    @Override
    @WebMethod(operationName = "create")
    public OBReminder create(@WebParam(name = "obreminder") OBReminder entity){
        entity = super.create(entity);
        return entity;
    }

    @PUT
    @Override
    @Consumes({"application/xml", "application/json"})
    public void edit(OBReminder entity) {
        super.edit(entity);
        this.getEntityManager().getEntityManagerFactory().getCache().evictAll();
    }

    @DELETE
    @Path("{id}")
    public void remove(@PathParam("id") Integer id) {
        super.remove(super.find(id));
    }

    @GET
    @Path("{id}")
    @Produces({"application/xml", "application/json"})
    public OBReminder find(@PathParam("id") Integer id) {
        return super.find(id);
    }

    @GET
    @Override
    @Produces({"application/xml", "application/json"})
    public List<OBReminder> findAll() {
        return super.findAll();
    }

    @GET
    @Path("{from}/{to}")
    @Produces({"application/xml", "application/json"})
    public List<OBReminder> findRange(@PathParam("from") Integer from, @PathParam("to") Integer to) {
        return super.findRange(new int[]{from, to});
    }

    @GET
    @Path("count")
    @Produces("text/plain")
    public String countREST() {
        return String.valueOf(super.count());
    }
    
    @GET
    @Path("runchecks")
    @Produces("text/plain")
    public String runChecks(){
        String retStr = "";
        List<OBReminder> rmdrs = super.findAll();
        rmdrsToRun.removeAll(rmdrsToRun);
        final Calendar calTdy = Calendar.getInstance();
        calTdy.set(Calendar.HOUR, 0);
        calTdy.set(Calendar.MINUTE, 0);
        calTdy.set(Calendar.MILLISECOND, 0);
        calTdy.set(Calendar.SECOND, 0);
        final Date today = calTdy.getTime();
        for(final OBReminder rmdr : rmdrs){
            loadRepeatDates(rmdr.getReminderDate(), RepetitionType.getType(rmdr.getRepetitionType()));
            Calendar cal = Calendar.getInstance();
            for(final OBAlarm alarm : rmdr.getAlarmCollection()){
                for(final Date dt : repeatDates){
                    cal.setTime(dt);
                    cal.add(Calendar.HOUR, (-1*alarm.getAlarmHours()));
                    cal.set(Calendar.HOUR, 0);
                    cal.set(Calendar.MINUTE, 0);
                    cal.set(Calendar.MILLISECOND, 0);
                    cal.set(Calendar.SECOND, 0);
                    final Date cmpDate = cal.getTime();
                    if(cmpDate.equals(today)){
                        //Add to todo list.
                        rmdrsToRun.add(new toRun(rmdr, alarm, dt));
                    }
                }
            }
        }
        
        if(rmdrsToRun!=null){
            //run reminders!
            SystemEmailer se = new SystemEmailer();
            GoogleCalendar gc = new GoogleCalendar();
            for(final toRun tr : rmdrsToRun){
                //Run function depending on settings of alarm type.
                switch(AlarmType.getType(tr.getAlarm().getAlarmType())){
                    case EMAIL:
                        se.SendReminderNotificationMail(tr.getRmdr(), tr.getAlarm(), tr.getDate(), em);
                        break;
                    case GOOGLE_CALENDAR:
                        gc.createReminderCalendarEntry(tr.rmdr, tr.getAlarm(), tr.getDate(), em);
                        break;
                    case TEXT_MESSAGE:
                        break;
                }
            }
        }
        return retStr;
    }
    
    //**************************************************************************
    //Repetition functions
    //**************************************************************************
    private void loadRepeatDates(final Date startDate, final RepetitionType rt){
        repeatDates.removeAll(repeatDates);
        
        TimeZone.setDefault(TimeZone.getTimeZone("MST"));
        Date today = new Date();
        startDate.setYear(today.getYear());
        
        final Calendar cal = Calendar.getInstance();
        cal.setTime(startDate);
        
        Calendar newCal = Calendar.getInstance();
        newCal.setTime(startDate);
        
        int year = 0;
        
        switch (rt) {
            case YEARLY:
                repeatDates.add(cal.getTime());
                return;
            case QUARTERLY:
                repeatDates.add(cal.getTime());
                newCal.add(Calendar.MONTH, 3);
                year = newCal.get(Calendar.YEAR);
                while(year == cal.get(Calendar.YEAR)){
                    repeatDates.add(newCal.getTime());
                    newCal.add(Calendar.MONTH, 3);
                    year = newCal.get(Calendar.YEAR);
                }
                return;
            case MONTHLY:
                repeatDates.add(cal.getTime());
                newCal.add(Calendar.MONTH, 1);
                year = newCal.get(Calendar.YEAR);
                while(year == cal.get(Calendar.YEAR)){
                    repeatDates.add(newCal.getTime());
                    newCal.add(Calendar.MONTH, 1);
                    year = newCal.get(Calendar.YEAR);
                }
                return;
            case WEEKLY:
                repeatDates.add(cal.getTime());
                newCal.add(Calendar.DATE, 7);
                year = newCal.get(Calendar.YEAR);
                while(year == cal.get(Calendar.YEAR)){
                    repeatDates.add(newCal.getTime());
                    newCal.add(Calendar.DATE, 7);
                    year = newCal.get(Calendar.YEAR);
                }
                return;
            case DAILY:
                repeatDates.add(cal.getTime());
                newCal.add(Calendar.DATE, 1);
                year = newCal.get(Calendar.YEAR);
                while(year == cal.get(Calendar.YEAR)){
                    repeatDates.add(newCal.getTime());
                    newCal.add(Calendar.DATE, 1);
                    year = newCal.get(Calendar.YEAR);
                }
                return;
            default:
                return;
        }
    }

    @Override
    protected EntityManager getEntityManager() {
        return em;
    }
}
